/*
ID: icerupt1
PROG: fence6
LANG: C++11
*/

//chapter 4 section 1
/* solution
 *
 *
 *
*/
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>

std::ifstream fin {"fence6.in" };
std::ofstream fout{"fence6.out"};

struct edge
{
	int len;
	std::vector<int> one_end;
	std::vector<int> other_end;
};

int const oo = 1<<27;
int const maxn = 102;
int map[maxn][maxn];
int dis[maxn][maxn];
int n, m;

std::vector<edge> es;
std::vector<std::vector<int>> points;
std::vector<std::vector<int>> edge_points;

bool equal(std::vector<int> const & a, std::vector<int> const & b)
{
	if (a.size() != b.size()) return false;
	for (int i = 0; i < (int)a.size(); i++)
		if (a[i] != b[i]) return false;
	return true;
}

bool less(std::vector<int> const & a, std::vector<int> const & b)
{
	int t = std::min(a.size(), b.size());
	for (int i = 0; i < t; i++) {
		if (a[i] == b[i]) continue;
		return (a[i] < b[i]);
	}
	return a.size() < b.size();
}

int main()
{
	fin >> n;
	es.resize(n);
	edge_points.resize(n);
	for (int i = 0, id, n1, n2; i < n; i++) {
		fin >> id; id--;
		fin >> es[id].len >> n1 >> n2;
		es[id].one_end.resize(n1);
		es[id].other_end.resize(n2);
		std::vector<int> points_one_end;
		std::vector<int> points_other_end;
		points_one_end.push_back(id);
		points_other_end.push_back(id);
		for (int j = 0, id_t; j < n1; j++) {
			fin >> id_t; id_t--;
			es[id].one_end[j] = id_t;
			points_one_end.push_back(id_t);
		}
		for (int j = 0, id_t; j < n2; j++) {
			fin >> id_t; id_t--;
			es[id].other_end[j] = id_t;
			points_other_end.push_back(id_t);
		}
		std::sort(points_one_end.begin(), points_one_end.end());
		std::sort(points_other_end.begin(), points_other_end.end());
		points.push_back(points_one_end);
		points.push_back(points_other_end);
	}

	//deduplicate
	std::sort(points.begin(), points.end(), less);
	for (auto i = 1; i < (int)points.size(); i++)
		if (equal(points[i-1], points[i]))
			points.erase(points.begin() + (--i));

	m = points.size();
	for (auto i = 0; i < m; i++)
		for (auto j : points[i])
			edge_points[j].push_back(i);

	std::fill(map[0], map[0] + maxn*maxn, oo);
	for (int i = 0; i < n; i++) {
		int x = edge_points[i][0], y = edge_points[i][1];
		map[x][y] = map[y][x] = es[i].len;
	}

	for (auto i = 0; i < m; i++)
		for (auto j = 0; j < m; j++) dis[i][j] = map[i][j];


	for (auto i = 0; i < m; i++) {
		for (auto j = 0; j < m; j++) {
			if (map[i][j] >= oo) std::cout << "* ";
			else				 std::cout << map[i][j] << ' ';
		}
		std::cout << '\n';
	}


	int ans = oo;

	//core part flyoed
	for (auto k = 0; k < m; k++) {
		for (auto i = 0; i < k; i++)
			for (auto j = i+1; j < k; j++)
				ans = std::min(ans, map[i][k] + map[k][j] + dis[i][j]);
		for (auto i = 0; i < m; i++)
			for (auto j = 0; j < m; j++)
				dis[i][j] = std::min(dis[i][j], dis[i][k] + dis[k][j]);
	}


	for (auto i = 0; i < m; i++) {
		for (auto j = 0; j < m; j++) {
			if (dis[i][j] >= oo) std::cout << "* ";
			else				 std::cout << dis[i][j] << ' ';
		}
		std::cout << '\n';
	}


	std::cout << ans << '\n';
	fout << ans << '\n';
}

